package org.dxy.trigger.http.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dxy.api.dto.request.mbom.*;
import org.dxy.api.dto.response.R;
import org.dxy.domain.command.mbom.*;
import org.dxy.domain.handler.mbom.*;
import org.dxy.infrastructure.persistent.po.query.MBOMViewPo;
import org.dxy.infrastructure.persistent.service.MBOMViewService;
import org.dxy.trigger.http.service.MBOMApplicationService;
import org.dxy.types.common.CommandResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * MBOM应用服务实现
 * @author dxy
 * @createTime 2025/9/10
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MBOMApplicationServiceImpl implements MBOMApplicationService {

    // Command Handlers (写操作)
    private final SyncMBOMFromEBOMCommandHandler syncMBOMFromEBOMCommandHandler;
    private final CreateMBOMCommandHandler createMBOMCommandHandler;
    private final UpdateMBOMCommandHandler updateMBOMCommandHandler;
    private final SubmitMBOMForReviewCommandHandler submitMBOMForReviewCommandHandler;
    private final ApproveMBOMCommandHandler approveMBOMCommandHandler;
    private final RejectMBOMCommandHandler rejectMBOMCommandHandler;
    private final ReleaseMBOMCommandHandler releaseMBOMCommandHandler;
    private final AssignMBOMToWorkOrderCommandHandler assignMBOMToWorkOrderCommandHandler;
    private final ObsoleteMBOMCommandHandler obsoleteMBOMCommandHandler;
    
    // Query Service (读操作)
    private final MBOMViewService mbomViewService;

    @Transactional
    @Override
    public R<Long> syncFromEBOM(SyncMBOMFromEBOMRequest request) {
        try {
            SyncMBOMFromEBOMCommand command = new SyncMBOMFromEBOMCommand(
                    request.getEbomId(),
                    request.getEbomVersion(),
                    request.getProductId());

            CommandResult<Long> result = syncMBOMFromEBOMCommandHandler.handle(command);
            
            if (result.success()) {
                // 保存基础读模型信息
                MBOMViewPo mbomView = MBOMViewPo.builder()
                        .id(result.data())
                        .ebomId(request.getEbomId())
                        .ebomVersion(request.getEbomVersion())
                        .productId(request.getProductId())
                        .status("DRAFT")
                        .build();
                
                mbomViewService.save(mbomView);
                
                return R.ok(result.data(), result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("从EBOM同步MBOM失败", e);
            return R.fail("从EBOM同步MBOM失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Long> create(CreateMBOMRequest request) {
        try {
            CreateMBOMCommand command = new CreateMBOMCommand(
                    request.getMbomCode(),
                    request.getMbomName(),
                    request.getProductId(),
                    request.getVersion());

            CommandResult<Long> result = createMBOMCommandHandler.handle(command);
            
            if (result.success()) {
                // 保存基础读模型信息
                MBOMViewPo mbomView = MBOMViewPo.builder()
                        .id(result.data())
                        .mbomCode(request.getMbomCode())
                        .mbomName(request.getMbomName())
                        .productId(request.getProductId())
                        .version(request.getVersion())
                        .status("DRAFT")
                        .build();
                
                mbomViewService.save(mbomView);
                
                return R.ok(result.data(), result.msg());
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("创建MBOM失败", e);
            return R.fail("创建MBOM失败: " + e.getMessage());
        }
    }

    @Override
    public R<Page<MBOMViewPo>> list(Page<MBOMViewPo> page, MBOMViewPo query) {
        try {
            LambdaQueryWrapper<MBOMViewPo> wrapper = new LambdaQueryWrapper<>();
            
            // 构建查询条件
            if (StringUtils.hasText(query.getMbomCode())) {
                wrapper.like(MBOMViewPo::getMbomCode, query.getMbomCode());
            }
            if (StringUtils.hasText(query.getMbomName())) {
                wrapper.like(MBOMViewPo::getMbomName, query.getMbomName());
            }
            if (query.getProductId() != null) {
                wrapper.eq(MBOMViewPo::getProductId, query.getProductId());
            }
            if (StringUtils.hasText(query.getStatus())) {
                wrapper.eq(MBOMViewPo::getStatus, query.getStatus());
            }
            if (StringUtils.hasText(query.getVersion())) {
                wrapper.eq(MBOMViewPo::getVersion, query.getVersion());
            }
            
            // 默认按创建时间倒序
            wrapper.orderByDesc(MBOMViewPo::getCreatedTime);
            
            Page<MBOMViewPo> result = mbomViewService.page(page, wrapper);
            return R.ok(result);
        } catch (Exception e) {
            log.error("查询MBOM列表失败", e);
            return R.fail("查询MBOM列表失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> update(Long id, UpdateMBOMRequest request) {
        try {
            UpdateMBOMCommand command = new UpdateMBOMCommand(
                    id,
                    request.getMbomName(),
                    request.getDescription());

            CommandResult<Void> result = updateMBOMCommandHandler.handle(command);
            
            if (result.success()) {
                // 更新读模型
                MBOMViewPo mbomView = mbomViewService.getById(id);
                if (mbomView != null) {
                    mbomView.setMbomName(request.getMbomName());
                    mbomView.setDescription(request.getDescription());
                    mbomViewService.updateById(mbomView);
                }
                
                return R.ok();
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("更新MBOM失败", e);
            return R.fail("更新MBOM失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> submitForReview(Long id, SubmitMBOMReviewRequest request) {
        try {
            SubmitMBOMForReviewCommand command = new SubmitMBOMForReviewCommand(
                    id,
                    request.getReviewerId(),
                    request.getSubmitComment());

            CommandResult<Void> result = submitMBOMForReviewCommandHandler.handle(command);
            
            if (result.success()) {
                // 更新读模型
                MBOMViewPo mbomView = mbomViewService.getById(id);
                if (mbomView != null) {
                    mbomView.setStatus("REVIEWING");
                    mbomView.setReviewerId(request.getReviewerId());
                    mbomView.setSubmitTime(LocalDateTime.now());
                    mbomViewService.updateById(mbomView);
                }
                
                return R.ok();
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("提交MBOM审核失败", e);
            return R.fail("提交MBOM审核失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> approve(Long id, ApproveMBOMRequest request) {
        try {
            ApproveMBOMCommand command = new ApproveMBOMCommand(
                    id,
                    request.getApproveComment());

            CommandResult<Void> result = approveMBOMCommandHandler.handle(command);
            
            if (result.success()) {
                // 更新读模型
                MBOMViewPo mbomView = mbomViewService.getById(id);
                if (mbomView != null) {
                    mbomView.setStatus("APPROVED");
                    mbomView.setReviewTime(LocalDateTime.now());
                    mbomViewService.updateById(mbomView);
                }
                
                return R.ok();
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("审核通过MBOM失败", e);
            return R.fail("审核通过MBOM失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> reject(Long id, RejectMBOMRequest request) {
        try {
            RejectMBOMCommand command = new RejectMBOMCommand(
                    id,
                    request.getRejectReason());

            CommandResult<Void> result = rejectMBOMCommandHandler.handle(command);
            
            if (result.success()) {
                // 更新读模型
                MBOMViewPo mbomView = mbomViewService.getById(id);
                if (mbomView != null) {
                    mbomView.setStatus("DRAFT"); // 拒绝后回到草稿状态
                    mbomView.setReviewTime(LocalDateTime.now());
                    mbomViewService.updateById(mbomView);
                }
                
                return R.ok();
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("审核拒绝MBOM失败", e);
            return R.fail("审核拒绝MBOM失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> release(Long id) {
        try {
            ReleaseMBOMCommand command = new ReleaseMBOMCommand(id);

            CommandResult<Void> result = releaseMBOMCommandHandler.handle(command);
            
            if (result.success()) {
                // 更新读模型
                MBOMViewPo mbomView = mbomViewService.getById(id);
                if (mbomView != null) {
                    mbomView.setStatus("RELEASED");
                    mbomView.setReleaseTime(LocalDateTime.now());
                    mbomViewService.updateById(mbomView);
                }
                
                return R.ok();
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("发布MBOM失败", e);
            return R.fail("发布MBOM失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> assignToWorkOrder(Long id, AssignMBOMToWorkOrderRequest request) {
        try {
            AssignMBOMToWorkOrderCommand command = new AssignMBOMToWorkOrderCommand(
                    id,
                    request.getWorkOrderId());

            CommandResult<Void> result = assignMBOMToWorkOrderCommandHandler.handle(command);
            
            if (result.success()) {
                return R.ok();
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("分配MBOM给工单失败", e);
            return R.fail("分配MBOM给工单失败: " + e.getMessage());
        }
    }

    @Transactional
    @Override
    public R<Void> obsolete(Long id, ObsoleteMBOMRequest request) {
        try {
            ObsoleteMBOMCommand command = new ObsoleteMBOMCommand(
                    id,
                    request.getObsoleteReason());

            CommandResult<Void> result = obsoleteMBOMCommandHandler.handle(command);
            
            if (result.success()) {
                // 更新读模型
                MBOMViewPo mbomView = mbomViewService.getById(id);
                if (mbomView != null) {
                    mbomView.setStatus("OBSOLETED");
                    mbomView.setObsoleteTime(LocalDateTime.now());
                    mbomViewService.updateById(mbomView);
                }
                
                return R.ok();
            } else {
                return R.fail(result.msg());
            }
        } catch (Exception e) {
            log.error("作废MBOM失败", e);
            return R.fail("作废MBOM失败: " + e.getMessage());
        }
    }

    @Override
    public R<MBOMViewPo> getById(Long id) {
        try {
            MBOMViewPo mbom = mbomViewService.getById(id);
            if (mbom == null) {
                return R.fail("MBOM不存在");
            }
            return R.ok(mbom);
        } catch (Exception e) {
            log.error("获取MBOM详情失败", e);
            return R.fail("获取MBOM详情失败: " + e.getMessage());
        }
    }

    @Override
    public R<List<MBOMViewPo>> getActiveByProductId(Long productId) {
        try {
            LambdaQueryWrapper<MBOMViewPo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MBOMViewPo::getProductId, productId)
                   .eq(MBOMViewPo::getStatus, "RELEASED")
                   .orderByDesc(MBOMViewPo::getVersion);
            
            List<MBOMViewPo> mboms = mbomViewService.list(wrapper);
            return R.ok(mboms);
        } catch (Exception e) {
            log.error("根据产品获取有效MBOM列表失败", e);
            return R.fail("根据产品获取有效MBOM列表失败: " + e.getMessage());
        }
    }

    @Override
    public R<List<MBOMViewPo>> getByStatus(String status) {
        try {
            LambdaQueryWrapper<MBOMViewPo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MBOMViewPo::getStatus, status)
                   .orderByDesc(MBOMViewPo::getCreatedTime);
            
            List<MBOMViewPo> mboms = mbomViewService.list(wrapper);
            return R.ok(mboms);
        } catch (Exception e) {
            log.error("根据状态获取MBOM列表失败", e);
            return R.fail("根据状态获取MBOM列表失败: " + e.getMessage());
        }
    }
}